package net.qiqbframework.loadhanding;

import net.qiqbframework.common.Registration;
import net.qiqbframework.common.utils.CollectionUtil;
import net.qiqbframework.messaging.annotation.*;
import net.qiqbframework.modelling.domain.AggregateModelFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 加载
 *
 * @param <T>
 */
public class AnnotationLoadHandlerAdapter<T> implements LoadMessageHandler {


    private final T target;

    private final AnnotatedHandlerInspector<T> handlerInspector;

    public AnnotationLoadHandlerAdapter(T annotatedLoader, HandlerParameterResolverFactory parameterResolverFactory,
                                        HandlerAttributesPostProcessor handlerAttributesPostProcessor,
                                        MessageHandlingMemberFactory handlerDefinition,
                                        AggregateModelFactory aggregateModelFactory) {
        this.target = annotatedLoader;
        this.handlerInspector = AnnotatedHandlerInspector.inspectType((Class<T>) annotatedLoader.getClass(), parameterResolverFactory, handlerAttributesPostProcessor, handlerDefinition);

    }


    public Registration subscribe(AggregateLoadBus loadBus) {
        Collection<Registration> subscriptions =
                supportedAggregateNames().stream()
                        .map(supportedCommand -> loadBus.subscribe(supportedCommand, this))
                        .collect(Collectors.toCollection(ArrayDeque::new));

        return () -> subscriptions.stream().map(Registration::cancel).reduce(Boolean::logicalOr).orElse(false);
    }


    @Override
    public Object handle(LoadMessage<?, ?> loadMessage) throws Exception {

        final List<MessageExecutableHandler> matchedMessageHandlingMember = handlerInspector.getHandlers(target.getClass())
                .filter(ch -> ch.canHandle(loadMessage))
                .toList();
        if (CollectionUtil.isEmpty(matchedMessageHandlingMember)) {
            return null;
        }
        if (matchedMessageHandlingMember.size() > 1) {
            throw new IllegalArgumentException("找到多个加载器");
        }
        final MessageExecutableHandler messageExecutableHandler = matchedMessageHandlingMember.get(0);
        return handlerInspector.chainedInterceptor(target.getClass()).handle(loadMessage, target, messageExecutableHandler);
    }


    private Set<String> supportedAggregateNames() {
        return handlerInspector.getAllHandlers()
                .values()
                .stream()
                .flatMap(Collection::stream)
                .map(ch -> ch.unwrap(LoadExecutableHandler.class).orElse(null))
                .filter(Objects::nonNull)
                .map(LoadExecutableHandler::aggregateNaming)
                .collect(Collectors.toSet());
    }


}
